#include <stdbool.h>
#include "clib_container_hash_set.h"


struct clib_container_hash_set {
    struct clib_container_hash_map *hash_map;

    void *(*mem_malloc_func)(size_t size);

    void (*mem_free_func)(void *block);

    void *(*mem_copy_func)(void *target,const void *src, size_t size);
};


int clib_container_hash_set_create_with_conf(struct clib_container_hash_set_conf *conf,
                                             struct clib_container_hash_set **hash_set) {

    clib_check_if_true_return_value(conf == NULL, CLIB_RES_PARAM_ERROR);
    clib_check_if_true_return_value(conf->mem_copy_func == NULL, CLIB_RES_PARAM_ERROR);
    clib_check_if_true_return_value(conf->mem_malloc_func == NULL, CLIB_RES_PARAM_ERROR);
    clib_check_if_true_return_value(conf->mem_free_func == NULL, CLIB_RES_PARAM_ERROR);

    if (conf->initial_capacity == 0){
        conf->initial_capacity = 8;
    }

    //构造hashmap参数
    struct clib_container_hash_map_conf map_conf;
    conf->mem_copy_func(&map_conf, conf, sizeof(struct clib_container_hash_map_conf));

    //创建hashmap
    struct clib_container_hash_map *map;
    int code = clib_container_hash_map_create_with_conf(&map_conf, &map);
    if (code != CLIB_RES_OK) {
        return code;
    }
    struct clib_container_hash_set *set = conf->mem_malloc_func(sizeof(struct clib_container_hash_set));
    if (!set) {
        clib_container_hash_map_destroy(map);
        return CLIB_RES_MEMORY_ERROR;
    }
    set->hash_map = map;
    set->mem_malloc_func = conf->mem_malloc_func;
    set->mem_copy_func = conf->mem_copy_func;
    set->mem_free_func = conf->mem_free_func;
    *hash_set = set;
    return CLIB_RES_OK;
}


void clib_container_hash_set_destroy(struct clib_container_hash_set *set) {
    clib_container_hash_map_destroy(set->hash_map);
    set->mem_free_func(set);
}

int clib_container_hash_set_add(struct clib_container_hash_set *set, void *element, void **pre_value) {
    return clib_container_hash_map_put(set->hash_map, element, element, pre_value);
}

int clib_container_hash_set_remove(struct clib_container_hash_set *set, void *element, void **pre_value) {
    return clib_container_hash_map_remove(set->hash_map, element, pre_value);
}

int clib_container_hash_set_remove_all(struct clib_container_hash_set *set, void *out_values[]) {
    return clib_container_hash_map_remove_all(set->hash_map, out_values);
}

bool clib_container_hash_set_contains(struct clib_container_hash_set *set, void *element) {
    return clib_container_hash_map_contains_key(set->hash_map, element);
}

size_t clib_container_hash_set_get_current_size(struct clib_container_hash_set *set) {
    return clib_container_hash_map_get_current_size(set->hash_map);
}

size_t clib_container_hash_set_get_values(struct clib_container_hash_set *set, void *out_values[]) {
    size_t current_size = clib_container_hash_map_get_current_size(set->hash_map);
    void *keys[current_size];
    clib_container_hash_map_get_keys(set->hash_map, keys);
    for (int i = 0; i < current_size; ++i) {
        clib_container_hash_map_get(set->hash_map, keys[i], &out_values[i]);
    }
    return current_size;
}
